<?php

/*
	Question2Answer (c) Gideon Greenspan

	http://www.question2answer.org/

	
	File: qa-include/qa-check-lang.php
	Version: See define()s at top of qa-include/qa-base.php
	Description: Development tool to see which language phrases are missing or unused


	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	More about this license: http://www.question2answer.org/license.php
*/

define('QA_BASE_DIR', dirname(dirname(empty($_SERVER['SCRIPT_FILENAME']) ? __FILE__ : $_SERVER['SCRIPT_FILENAME'])) . '/');

require 'qa-base.php';
require_once QA_INCLUDE_DIR . 'qa-app-users.php';

if (qa_get_logged_in_level() < QA_USER_LEVEL_ADMIN)
    qa_redirect('admin/general', null, qa_opt('site_url'));

header('Content-type: text/html; charset=utf-8');
?>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>Question2Answer Language Check</title>
    <style>
        code {
            font-size: 125%;
        }
    </style>
</head>
<body style="font-family:arial; font-size:12px;">
<?php

function get_phrase_substitutions($phrase)
{
    $substitutions = array();

    if (preg_match_all('/\^(([0-9]+)|([a-z_]+)|)/', $phrase, $matches))
        foreach ($matches[0] as $match)
            @$substitutions[$match]++;

    return $substitutions;
}

echo '<font color="#cc0000"><code>Dark red = important to review.</code></font><br>';
echo '<font color="#cc9999"><code>Light red = probably safe to ignore.</code></font>';

echo '<h1>Checking US English files in <code>qa-include</code>...</h1>';

$includefiles = array_merge(glob(QA_INCLUDE_DIR . 'qa-*.php'), glob(QA_PLUGIN_DIR . '*/qa-*.php'));

$definite = array();
$probable = array();
$possible = array();
$defined = array();
$english = array();
$backmap = array();
$substitutions = array();

output_start_includes();

foreach ($includefiles as $includefile) {
    $contents = file_get_contents($includefile);

    preg_match_all('/qa_lang[a-z_]*\s*\(\s*[\'\"]([a-z]+)\/([0-9a-z_]+)[\'\"]/', $contents, $matches, PREG_SET_ORDER);

    foreach ($matches as $matchparts)
        if ($matchparts[2] == 'date_month_') { // special case for month names
            for ($month = 1; $month <= 12; $month++)
                @$definite[$matchparts[1]][$matchparts[2] . $month]++;

        } else
            @$definite[$matchparts[1]][$matchparts[2]]++;

    preg_match_all('/[\'\"]([a-z]+)\/([0-9a-z_]+)[\'\"]/', $contents, $matches, PREG_SET_ORDER);

    foreach ($matches as $matchparts)
        @$probable[$matchparts[1]][$matchparts[2]]++;

    if (preg_match('|/qa-include/qa-lang-([a-z]+)\.php$|', $includefile, $matches)) { // it's a lang file
        $prefix = $matches[1];

        output_reading_include($includefile);
        $phrases = @include $includefile;

        foreach ($phrases as $key => $value) {
            @$defined[$prefix][$key]++;
            $english[$prefix][$key] = $value;
            $backmap[$value][] = array('prefix' => $prefix, 'key' => $key);
            $substitutions[$prefix][$key] = get_phrase_substitutions($value);
        }

    } else { // it's a different file
        preg_match_all('/[\'\"\/]([0-9a-z_]+)[\'\"]/', $contents, $matches, PREG_SET_ORDER);

        foreach ($matches as $matchparts)
            @$possible[$matchparts[1]]++;
    }
}

output_finish_includes();

foreach ($definite as $key => $valuecount)
    foreach ($valuecount as $value => $count)
        if (!@$defined[$key][$value])
            output_lang_issue($key, $value, 'used by ' . $count . ' file/s but not defined');

foreach ($defined as $key => $valuecount)
    foreach ($valuecount as $value => $count)
        if ((!@$definite[$key][$value]) && (!@$probable[$key][$value]) && (!@$possible[$value]))
            output_lang_issue($key, $value, 'defined but apparently not used');

foreach ($backmap as $phrase => $where)
    if (count($where) > 1)
        foreach ($where as $onewhere)
            output_lang_issue($onewhere['prefix'], $onewhere['key'], 'contains the shared phrase "' . $phrase . '"', false);

require_once QA_INCLUDE_DIR . 'qa-app-admin.php';

$languages = qa_admin_language_options();
unset($languages['']);

foreach ($languages as $code => $language) {
    echo '<h1>Checking ' . $language . ' files in <code>qa-lang/' . $code . '</code>...</h1>';

    $langdefined = array();
    $langdifferent = array();
    $langsubstitutions = array();
    $langincludefiles = glob(QA_LANG_DIR . $code . '/qa-*.php');
    $langnewphrases = array();

    output_start_includes();

    foreach ($langincludefiles as $langincludefile)
        if (preg_match('/qa-lang-([a-z]+)\.php$/', $langincludefile, $matches)) { // it's a lang file
            $prefix = $matches[1];

            output_reading_include($langincludefile);
            $phrases = @include $langincludefile;

            foreach ($phrases as $key => $value) {
                @$langdefined[$prefix][$key]++;
                $langdifferent[$prefix][$key] = ($value != @$english[$prefix][$key]);
                $langsubstitutions[$prefix][$key] = get_phrase_substitutions($value);
            }
        }

    output_finish_includes();

    foreach ($langdefined as $key => $valuecount)
        foreach ($valuecount as $value => $count) {
            if (!@$defined[$key][$value])
                output_lang_issue($key, $value, 'defined but not in US English files');

            elseif (!$langdifferent[$key][$value])
                output_lang_issue($key, $value, 'identical to US English files', false); else
                foreach ($substitutions[$key][$value] as $substitution => $subcount)
                    if (!@$langsubstitutions[$key][$value][$substitution])
                        output_lang_issue($key, $value, 'omitted the substitution ' . $substitution);
                    elseif ($subcount > @$langsubstitutions[$key][$value][$substitution])
                        output_lang_issue($key, $value, 'has fewer of the substitution ' . $substitution);
        }

    foreach ($defined as $key => $valuecount) {
        $showaserror = !(($key == 'admin') || ($key == 'options') || ($code == 'en-GB'));

        if (@$langdefined[$key]) {
            if (count($langdefined[$key]) < (count($valuecount) / 2)) { // only a few phrases defined
                output_lang_issue($key, null, 'few translations provided so will use US English defaults', $showaserror);

            } else
                foreach ($valuecount as $value => $count)
                    if (!@$langdefined[$key][$value]) {
                        output_lang_issue($key, $value, 'undefined so will use US English defaults', $showaserror);
                        $langnewphrases[$key][$value] = $english[$key][$value];
                    }
        } else
            output_lang_issue($key, null, 'no translations provided so will use US English defaults', $showaserror);
    }

    foreach ($langnewphrases as $prefix => $phrases) {
        echo '<h2>' . $language . ' phrases to add to <code>qa-lang/' . $code . '/qa-lang-' . $prefix . '.php</code>:</h2>';

        echo 'Copy and paste this into the middle of <code>qa-lang/' . $code . '/qa-lang-' . $prefix . '.php</code> then translate the right-hand side after the <code>=></code> symbol.';

        echo '<pre>';

        foreach ($phrases as $key => $value)
            echo '<span style="font-size:25%;">' . "\t\t</span>'" . $key . "' => \"" . strtr($value, array('\\' => '\\\\', '"' => '\"', '$' => '\$', "\n" => '\n', "\t" => '\t')) . "\",\n";

        echo '</pre>';
    }
}


function output_lang_issue($prefix, $key, $issue, $error = true)
{
    echo '<font color="' . ($error ? '#cc0000' : '#cc9999') . '"><code>';

    echo 'qa-lang-<b>' . qa_html($prefix) . '</b>.php:';

    if (strlen($key))
        echo "'<b>" . qa_html($key) . "</b>'";

    echo '</code></font> &nbsp; ' . qa_html($issue) . '<br>';
}


function output_start_includes()
{
    global $oneread;

    $oneread = false;

    echo '<p style="font-size:80%; color:#999;">Reading: ';
}


function output_reading_include($file)
{
    global $oneread;

    echo ($oneread ? ', ' : '') . htmlspecialchars(basename($file));
    flush();

    $oneread = true;
}


function output_finish_includes()
{
    echo '</p>';
}


echo '<h1>Finished scanning for problems!</h1>';

?>

</body>
</html>